package com.shanzmoo.h5.manager;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.NumberUtil;
import com.alibaba.fastjson.JSON;
import com.shanzmoo.base.bean.PageRespBase;
import com.shanzmoo.base.bean.SResponse;
import com.shanzmoo.base.constant.Constant;
import com.shanzmoo.base.constant.MallOrderStatus;
import com.shanzmoo.base.exception.MallOrderException;
import com.shanzmoo.core.service.IMallOrderRedisService;
import com.shanzmoo.core.util.RedisCoreKeyUtils;
import com.shanzmoo.db.mall.entity.MallOrderDetailEntity;
import com.shanzmoo.db.mall.entity.MallOrderEntity;
import com.shanzmoo.db.mall.entity.vo.MallOrderDetailVO;
import com.shanzmoo.db.mall.service.IMallOrderDetailService;
import com.shanzmoo.db.mall.service.IMallOrderService;
import com.shanzmoo.db.order.entity.dto.MallOrderDeatilRedisDTO;
import com.shanzmoo.db.order.entity.dto.MallOrderRedisDTO;
import com.shanzmoo.h5.domain.vo.MallOrderBriefVO;
import com.shanzmoo.h5.domain.vo.MallOrderVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 *
 *
 * @author： Gzhao 2021/2/3
 */
@Slf4j
@Component
public class WapMallOrderManager {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private IMallOrderService mallOrderService;
    @Autowired
    private IMallOrderDetailService mallOrderDetailService;
    @Autowired
    private IMallOrderRedisService mallOrderRedisService;

    @Transactional(rollbackFor = Exception.class)
    public String addOrder(MallOrderEntity orderEntity, List<MallOrderDetailEntity> mallOrderDetailEntityList) {
        // 商品总金额
        BigDecimal goodsAmount = new BigDecimal(0);

        for (MallOrderDetailEntity detail : mallOrderDetailEntityList) {
            BigDecimal totalPrice = NumberUtil.mul(detail.getSkuNum(), detail.getUnitPrice());
            detail.setTotalPrice(totalPrice);

            goodsAmount = NumberUtil.add(goodsAmount, totalPrice);
        }
        // 订单总金额
        BigDecimal amount = NumberUtil.add(goodsAmount, orderEntity.getFreight());
        // 实付金额
        BigDecimal receiveAmount = amount;

        orderEntity.setAmount(amount);
        orderEntity.setGoodsAmount(goodsAmount);
        orderEntity.setReceiveAmount(receiveAmount);

        mallOrderService.save(orderEntity);

        mallOrderDetailEntityList.forEach(e -> {
            e.setOrderId(orderEntity.getId());
        });
        mallOrderDetailService.saveBatch(mallOrderDetailEntityList);

        // 添加订单缓存
        mallOrderRedisService.addOneOrderRedis(mallOrderService.getById(orderEntity.getId()), mallOrderDetailEntityList);

        return orderEntity.getOrderNo();
    }

    public MallOrderVO getInfo(Integer orderId, Integer memberId) {
        String orderStr = (String) stringRedisTemplate.opsForHash().get(RedisCoreKeyUtils.installAllOrderListKey(), String.valueOf(orderId));

        MallOrderRedisDTO orderRedisDTO = JSON.parseObject(orderStr, MallOrderRedisDTO.class);
        if (!Integer.valueOf(memberId).equals(orderRedisDTO.getMemberId())) {
            throw new MallOrderException("未查询到订单");
        }

        MallOrderVO orderVO = MallOrderVO.create(orderRedisDTO);

//        String orderDetailStr = (String) stringRedisTemplate.opsForHash().get(RedisKeyUtils.installOrderDetailListKey(), String.valueOf(orderId));
//        List<MallOrderDeatilRedisDTO> orderDetailList = JSON.parseArray(orderDetailStr, MallOrderDeatilRedisDTO.class);
//        orderVO.setOrderDetailList(MallOrderDetailVO.createList(orderDetailList));

        List<MallOrderDetailVO> orderDetailList = mallOrderDetailService.getOrderDetailList(orderId);
        orderVO.setOrderDetailList(orderDetailList);

        return orderVO;
    }

    public PageRespBase<MallOrderBriefVO> queryList(String memberId, Integer pageNum, Integer pageSize, Integer status) {
        // 1.获取人员订单缓存
        if (!stringRedisTemplate.opsForHash().hasKey(RedisCoreKeyUtils.installMemberOrderListKey(), memberId)) {
            mallOrderRedisService.refreshAllOrderRedis();
        }

        String memberOrderIsStr = (String) stringRedisTemplate.opsForHash()
                .get(RedisCoreKeyUtils.installMemberOrderListKey(), memberId);
        List<Integer> orderIds = JSON.parseArray(memberOrderIsStr, Integer.class);
        if (CollectionUtil.isEmpty(orderIds)) {
            return PageRespBase.empty(pageSize);
        }
        CollectionUtil.sort(orderIds, (o1, o2) -> {return o2-o1;});
        // 2.对人员订单缓存数据分页
        List<Object> resultIds = new ArrayList<>();
        for (int i = (pageNum - 1) * pageSize; i < pageNum * pageSize && i < orderIds.size(); i++) {
            resultIds.add(String.valueOf(orderIds.get(i)));
        }

        // 3.从全量的订单数据中获取订单信息
        List<Object> resultList = stringRedisTemplate.opsForHash().multiGet(RedisCoreKeyUtils.installAllOrderListKey(), resultIds);
        List<MallOrderRedisDTO> allRedistList = resultList.stream()
                .map(e -> JSON.parseObject(e.toString(), MallOrderRedisDTO.class))
                .filter(e -> status == null || (status != null && e.getStatus().equals(status)))
                .collect(Collectors.toList());

        Collections.sort(allRedistList, ((o1, o2) -> {
            return (int)(o2.getCreateTime().toEpochSecond(ZoneOffset.of("+8")) - o1.getCreateTime().toEpochSecond(ZoneOffset.of("+8")));
        }));

        List<MallOrderBriefVO> reList = allRedistList.stream()
                .map(e -> {
                    MallOrderBriefVO orderBriefVO = MallOrderBriefVO.create(e);

                    String orderDetailStr = (String) stringRedisTemplate.opsForHash().get(RedisCoreKeyUtils.installOrderDetailListKey(), String.valueOf(orderBriefVO.getId()));
                    List<MallOrderDeatilRedisDTO> orderDetailList = JSON.parseArray(orderDetailStr, MallOrderDeatilRedisDTO.class);

                    orderBriefVO.setOrderDetailList(MallOrderDetailVO.createList(orderDetailList));

                    return orderBriefVO;
                })
                .collect(Collectors.toList());

        return PageRespBase.create(orderIds.size(), pageNum, pageSize, reList);
    }

    @Transactional(rollbackFor = Exception.class)
    public SResponse<Boolean> cancel(Integer orderId, Integer memberId) {
        MallOrderEntity order = mallOrderService.getById(orderId);
        if (!order.getMemberId().equals(memberId)) {
            return SResponse.fail(Constant.ERRCODE_LOGIC, "未获取到有效的订单信息");
        }

        if (order.getStatus() != MallOrderStatus.WAIT_PAY) {
            return SResponse.fail(Constant.ERRCODE_LOGIC, "只允许取消未支付订单");
        }

        order.setStatus(MallOrderStatus.CLOSED);
        mallOrderService.updateById(order);

        mallOrderRedisService.removeMemberOrder(orderId, memberId);

        return SResponse.ok(Boolean.TRUE);
    }

    @Transactional(rollbackFor = Exception.class)
    public SResponse<Boolean> confirmReceipt(Integer orderId, Integer memberId) {
        MallOrderEntity order = mallOrderService.getById(orderId);
        if (!order.getMemberId().equals(memberId)) {
            return SResponse.fail(Constant.ERRCODE_LOGIC, "未获取到有效的订单信息");
        }

        if (order.getStatus() != MallOrderStatus.ALREADY_SEND) {
            return SResponse.fail(Constant.ERRCODE_LOGIC, "只允许操作未支付订单");
        }

        order.setStatus(MallOrderStatus.FINISH);
        mallOrderService.updateById(order);

        mallOrderRedisService.updateOrder(orderId);

        return SResponse.ok(Boolean.TRUE);
    }

}
